package cat.sun.activities;

import cat.sun.R;
import cat.sun.dialogs.HelpDialog;
import cat.sun.dialogs.QuitDialog;
import cat.sun.graphics.DialogsViewer;
import cat.sun.graphics.FieldBitmapMaker;
import cat.sun.graphics.MyView;
import cat.sun.listeners.BombChangeListener;
import cat.sun.listeners.ResultListener;
import cat.sun.logic.GameManager;
import cat.sun.stats.Stats;
import cat.sun.themes.GetThemePackage;
import cat.sun.themes.ThemeConstants;
import cat.sun.themes.ThemeName;
import cat.sun.themes.ThemePackage;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;

public class Game extends FragmentActivity implements OnClickListener
{
	public static final String bundleName = "bundle";
	public static final String scaleSave = "scale";	

	private FieldBitmapMaker fieldBitmapMaker = null;
	private MyView fieldView = null;
	private TimeChange timeChange = null;
	private GameManager gameManager = null;
	private TextView timeView = null;
	private TextView bombsView = null;
	private ImageView pause = null;
	private ImageView resume = null;
	private ImageView back = null;
	private ImageView restart = null;
	
	private FragmentActivity activity;	
	private ThemePackage themePackage;
	private Stats stats;

	private State state = State.created;
	private PauseReason pauseReason;
	
	public enum State
	{
		created("created"), playing("playing"), paused("paused"), endgame("endgame");
		
		private String name;
		
		private State(String name)
		{
			this.name = name;
		}
		
		public String toString() 
		{
			return this.name;
		};
	};	
	
	public enum PauseReason
	{
		program("program"), user("user");
		
		private String name;
		
		private PauseReason(String name)
		{
			this.name = name;
		}
		
		public String toString() 
		{
			return this.name;
		};
	};	
	
	public enum ResumeReason
	{
		program, user
	};	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.game); 
        this.activity = this;
        
		this.timeView = (TextView) findViewById(R.id.gameTimeView);	
		this.bombsView = (TextView) findViewById(R.id.gameBombsView);
		this.pause = (ImageView) findViewById(R.id.imagePause);
		this.resume = (ImageView) findViewById(R.id.imageResume);
		this.fieldView = (MyView) findViewById(R.id.fieldView);
		this.back = (ImageView) findViewById(R.id.imageBack);
		this.restart = (ImageView) findViewById(R.id.imageRestart);
		
		resume.setVisibility(View.GONE);
		back.setOnClickListener(this);		
		restart.setOnClickListener(this);		
		this.resume.setOnClickListener(this);
		this.pause.setOnClickListener(this);
		
		CreateGame();
		
		if (savedInstanceState != null)
		{						
			this.gameManager.setSavedState(savedInstanceState);
			this.fieldView.setSavedState(savedInstanceState);
			String stateString = savedInstanceState.getString("game_state");
			State savedState = State.created; 
			for (State s:State.values())
			{
				if (stateString.equals(s.toString())) {savedState = s; break;}
			}
			this.state = savedState;
			if (state == State.paused)
			{
				this.setGraphicsPause();
			}			
			String pauseString = savedInstanceState.getString("game_pause");			
			if (pauseString.equals(PauseReason.user.toString())) this.pauseReason = PauseReason.user; else this.pauseReason = PauseReason.program;						
		}
	}
	
	private void CreateGame()
	{
		state = State.created;
		pauseReason = PauseReason.program;
		
		int width = getIntent().getExtras().getInt("width");
		int height = getIntent().getExtras().getInt("height");
		int bombs = getIntent().getExtras().getInt("bombs");		

		this.themePackage = GetThemePackage.getThemePackage(getSharedPreferences(ThemeConstants.bundleTag, 0).getString(ThemeConstants.savedTheme, ThemeName.DEFAULT_HOLO_DARK_THEME.toString()), this);
		fieldBitmapMaker = new FieldBitmapMaker(this.themePackage,Config.ARGB_8888,height,width);
		
		this.gameManager = new GameManager(width, height, bombs, bombChangeListener, resultListener);
		
		this.stats = new Stats(getSharedPreferences(getIntent().getExtras().getString("Table"), 0),getIntent().getExtras().getString("Table"),getResources());		
		boolean hasToVibrate = getSharedPreferences(Main.OPTIONS, 0).getBoolean(Main.VIBRATION, true);		
		fieldView.setStartUp(gameManager,hasToVibrate,fieldBitmapMaker);
		
		setGraphicsResume();
		
		this.timeChange = new TimeChange();
		this.timeChange.start();
	}
	
	@Override
	public void onClick(View v) 
	{
		switch (v.getId()) {
		case R.id.imagePause:
			this.Pause(PauseReason.user);
			break;
		case R.id.imageResume:
			this.Resume(ResumeReason.user);
		break;
		case R.id.imageRestart:
			this.CreateGame();
			break;
		case R.id.imageBack:
			if (this.state == State.playing) this.Pause(PauseReason.user);
			HelpDialog helpDialog = HelpDialog.newInstance();
			helpDialog.show(activity.getSupportFragmentManager(), "help_dialog");
			break;
		default:
			break;
		}
	}
	
	private ResultListener resultListener = new ResultListener() 
	{		
		@Override
		public void onWin() 
		{
			state = State.endgame;
			gameManager.EndTime();	
			DialogsViewer.showWinDialog(activity, stats, gameManager.resultedTime());
		}
		
		@Override
		public void onStarted() 
		{
			state = State.playing;
			gameManager.startTime();			
		}
		
		@Override
		public void onLose() 
		{
			state = State.endgame;
			gameManager.EndTime();	
			DialogsViewer.showLoseToast(activity);
		}
	};
	
	private BombChangeListener bombChangeListener = new BombChangeListener() 
	{		
		@Override
		public void onBombsChangeed(int newCount, int bombsAll) 
		{
			bombsView.setText(Integer.toString(newCount)+"/"+Integer.toString(bombsAll));
		}
	};		
	
	public void Resume(ResumeReason reason)
	{
		if (this.state != State.paused) return;
		if (this.state == State.paused && pauseReason == PauseReason.user && reason == ResumeReason.program) return;
		this.state = State.playing;
		gameManager.ResumeTime();
		this.setGraphicsResume();
		if (this.timeChange == null)
		{
			this.timeChange = new TimeChange();
			this.timeChange.start();
		}
	}
	
	public void Pause(PauseReason pauseReason)
	{
		if (this.state != State.playing) return;
		this.state = State.paused;
		this.pauseReason = pauseReason;
		gameManager.PauseTime();
		this.setGraphicsPause();
		if (timeChange != null)
		{
			this.timeChange.interrupt();
			this.timeChange = null;
		}
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) 
	{
		super.onSaveInstanceState(outState);
		this.gameManager.getSaveBundle(outState);
		this.fieldView.getSaveInstance(outState);
		outState.putString("game_state", this.state.toString());	
		outState.putString("game_pause", pauseReason.toString());
	}
	
	@Override
	protected void onPause() 
	{
		super.onPause();
		this.Pause(PauseReason.program);		
	}
	
	@Override
	protected void onResume() 
	{
		super.onResume();
		this.Resume(ResumeReason.program);		
	}
	
	@Override
	public void onBackPressed() 
	{
		if (this.state == State.playing) Pause(PauseReason.user);
		if (this.state == State.playing || this.state == State.paused)
		{
			QuitDialog quitDialog = QuitDialog.newInstance();
			quitDialog.show(activity.getSupportFragmentManager(), "quit_dialog");
		}
		else finish();
	}
	
	@Override
	protected void onDestroy() 
	{
		super.onDestroy();
		if (this.timeChange != null)
		{
			timeChange.interrupt();
			timeChange = null;
		}
		Editor editer = getSharedPreferences(bundleName, 0).edit();
		editer.putFloat(scaleSave, fieldView.getMyScaleFactor());
		editer.commit();
	}
	
	private void setGraphicsPause()
	{
		this.resume.setVisibility(View.VISIBLE);
		this.fieldView.setVisibility(View.GONE);
		this.pause.setImageResource(R.drawable.button_pause_grey_full);
		this.pause.setEnabled(false);
	}
	
	private void setGraphicsResume()
	{
		this.fieldView.setVisibility(View.VISIBLE);
		this.resume.setVisibility(View.GONE);
		this.pause.setImageResource(R.drawable.button_pause_full);
		this.pause.setEnabled(true);
	}

	final Handler changeTime = new Handler() 
	{
        @Override
        public void handleMessage(Message msg)
        {
        	timeView.setText(String.format("%.1f",((float)gameManager.getCurrentTime(state))/1000));
        }
    };
 		
	private class TimeChange extends Thread
	{
		@Override
		public void run() 
		{
			while (!this.isInterrupted())
			{
				changeTime.sendEmptyMessage(0);
				try {
					sleep(100);
				} catch (InterruptedException e) 
				{
					e.printStackTrace();
					this.interrupt();
				}
			}
		}	
	}	
	
}
